#include "Connection.h"
#include <Windows.h>
#include <WinSock.h>
#include <process.h>

#define Test
#include <iostream>
using std::cout;
#define ENDTest
#pragma comment(lib, "ws2_32.lib")

Connection::Connection(int sock, string localIp, int localPort, 
					   string remoteIp, int remotePort)
{
	_sock = sock;
	_errorMessage = "";

	_localIp = localIp;
	_localPort = localPort;

	_remoteIp = remoteIp;
	_remotePort = remotePort;
}

Connection::~Connection(void)
{
}

string Connection::GetErrorMessage()
{
	return _errorMessage;
}

bool Connection::Write(char* buffer, int offset, int length)
{
	if(_sock == -1)
	{
		_errorMessage = "invalid connection";
		return false;
	}

	if (send(_sock, buffer+offset, length, 0) == -1)
	{
		_errorMessage = "fail to send message";
		return false;
	}
	return true;
}

int Connection::Read(char* buffer, int offset, int length)
{
	if(_sock == -1)
	{
		_errorMessage = "invalid connection";
		return false;
	}

	int size = recv(_sock, buffer + offset, length, 0);
	if (size == -1)
	{
		_errorMessage = "fail to read";
	}
	return size;
}

bool Connection::BeginRead(char* buffer, int offset, int length, void (*completeHandler)(void))
{
	if (_sock == -1)
	{
		_errorMessage = "invalid connection";
		return false;
	}

	_readBuf = buffer;
	_readOffset = offset;
	_readLength = length;

	readComplete = completeHandler;

	//readComplete();
	union
	{
		void (*threadProc)(void*);
		void (Connection::*memProc)(void*);
	}Cast;

	Cast.memProc = &Connection::readThread;

	_beginthread(Cast.threadProc, 0, this);
	//_beginthread(readThread1, 0, 0);
	return true;
}

void Connection::Dispose()
{
	_sock = -1;
}

bool Connection::IsValid()
{
	return (_sock > -1);
}

string Connection::GetLocalIp()
{
	return _localIp;
}

string Connection::GetRemoteIp()
{
	return _remoteIp;
}

int Connection::GetLocalPort()
{
	return _localPort;
}

int Connection::GetRemotePort()
{
	return _remotePort;
}

void Connection::readThread(void* arg)
{
	Connection *con = (Connection*)arg;
	con->_readBytes = con->Read(con->_readBuf, con->_readOffset, con->_readLength);
	con->readComplete();
}

int Connection::EndRead()
{
	return _readBytes;
}